﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GmepModelInterface.h"
#include "IGmepConstDefinition.h"
#include "IDbObject.h"
#include "ICopyContext.h"
#include "ICopyStrategyReporter.h"

namespace
{
    using gcmp::ElementId;
    using gcmp::IElement;
    using gcmp::IDbObject;
    using gcmp::IElementParentReporter;
    using gcmp::OwnerPtr;
}

namespace gmep
{
    class IRoutingPreferenceRule;
    class RoutingConditions;

    /// \brief 管道配置类型哈希实现
    struct RoutingPreferenceRuleGroupTypeHash
    {
        std::size_t operator()(RoutingPreferenceRuleGroupType key) const
        {
            return std::hash<Int32>()((Int32)key);
        }
    };

    /// \brief 管道配置管理器各类型输入参数
    using RoutingPreferenceManagerInputData = std::unordered_map<RoutingPreferenceRuleGroupType, std::vector<std::tuple<ElementId, double, double>>>;

    /// \brief 管道配置管理器输入参数
    struct RoutingPreferenceManagerInput
    {
    public:
        RoutingPreferenceManagerInput() : OwnerElement(nullptr), JunctionType(PreferredJunctionType::TeeJunction){}
        IElement* OwnerElement;
        PreferredJunctionType JunctionType;
        RoutingPreferenceManagerInputData Data;
    };

    /// \brief 管道配置管理器
    class GMEP_MODEL_INTERFACE_EXPORT IRoutingPreferenceManager : public IDbObject
    {
        DEFINE_CAST_DERIVED(IRoutingPreferenceManager, IDbObject);
    public:
        /// \brief 析构函数
        virtual ~IRoutingPreferenceManager();

    public:
        /// \brief 获得该外部对象所属Element
        /// \return 所属Element
        virtual const IElement* GetOwnerElement() const = 0;

        /// \brief 获得该外部对象所属Element
        /// \return 所属Element
        virtual IElement* GetOwnerElement() = 0;

        /// \brief 设置该行为所属Element
        /// \param pOwnerElement 所属Element
        /// \return bool
        virtual bool SetOwnerElement(IElement* pOwnerElement) = 0;

        /// \brief 获得三通接头类型
        virtual PreferredJunctionType GetPreferredJunctionType()const = 0;

        /// \brief 设置三通接通类型
        virtual bool SetPreferredJunctionType(PreferredJunctionType preferredJunctionType) = 0;

        /// \brief 为指定管道配置类型添加配置规则（添加到尾部）
        /// 
        /// \param RoutingPreferenceRuleGroupType groupType 管道配置类型
        /// \param gcmp::OwnerPtr<IRoutingPreferenceRule> rule 配置规则
        /// \return bool 是否成功
        virtual bool AddRule(RoutingPreferenceRuleGroupType groupType, gcmp::OwnerPtr<IRoutingPreferenceRule> rule) = 0;

        /// \brief 为指定管道配置类型添加指定索引的配置规则
        /// 
        /// \param RoutingPreferenceRuleGroupType groupType 管道配置类型
        /// \param gcmp::OwnerPtr<IRoutingPreferenceRule> rule 配置规则
        /// \param int index 添加索引位置
        /// \return bool 是否成功
        virtual bool AddRule(RoutingPreferenceRuleGroupType groupType, gcmp::OwnerPtr<IRoutingPreferenceRule> rule, int index) = 0;

        /// \brief 根据配置条件获得对应管道配置类型的管段id或者管件类型id
        /// 
        /// \param RoutingPreferenceRuleGroupType groupType 管道配置类型
        /// \param const RoutingConditions & conditions 配置条件
        /// \return gcmp::ElementId 管段id或者管件类型id
        virtual ElementId GetMepPartId(RoutingPreferenceRuleGroupType groupType, const RoutingConditions& conditions)const = 0;

        /// \brief 根据配置条件获得Tap型三通的类型id
        /// 
        /// \param const RoutingConditions & conditions 配置条件
        /// \return gcmp::ElementId Tap型三通的类型id
        virtual ElementId GetTapPartId(const RoutingConditions& conditions)const = 0;

        /// \brief 获得指定管道配置类型的配置规则个数
        virtual int GetNumberOfRules(RoutingPreferenceRuleGroupType eGroupType)const = 0;

        /// \brief 获得指定管道配置类型指定索引的配置规则
        /// 
        /// \param RoutingPreferenceRuleGroupType groupType 管道配置类型
        /// \param int index 指定索引
        /// \return const gmep::IRoutingPreferenceRule* 配置规则
        virtual const IRoutingPreferenceRule* GetRule(RoutingPreferenceRuleGroupType groupType, int index)const = 0;

        /// \brief 获得指定管道配置类型指定索引的配置规则
        /// 
        /// \param RoutingPreferenceRuleGroupType groupType 管道配置类型
        /// \param int index 指定索引
        /// \return const gmep::IRoutingPreferenceRule* 配置规则
        virtual IRoutingPreferenceRule* GetRule(RoutingPreferenceRuleGroupType groupType, int index) = 0;

        /// \brief 删除指定管道配置类型中索引为index的配置规则
        /// 
        /// \param RoutingPreferenceRuleGroupType groupType 管道配置类型
        /// \param int index 索引
        /// \return bool 是否删除
        virtual bool RemoveRule(RoutingPreferenceRuleGroupType groupType, int index) = 0;

        /// \brief 清除所有配置规则
        virtual bool ClearRules() = 0;

        /// \brief 一次性设置所有配置规则
        virtual bool SetRules(const RoutingPreferenceManagerInputData& rulesData) = 0;

        /// \brief 处理强弱依赖关系，开发者不需要主动调用
        virtual void UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds) = 0;
        /// \brief 处理强弱依赖关系，开发者不需要主动调用
        virtual void ReportParents(IElementParentReporter& elementParentReporter) const = 0;
        ///\brief 报告拷贝策略，特别是对于报告为弱关系的ID；
        virtual void Report(const gcmp::ICopyContext & copyContext, gcmp::ICopyStrategyReporter& reporter) const =0;
    };
}
